package com.belf.console.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.belf.common.core.domain.AjaxResult;
import com.belf.common.utils.DateUtils;
import com.belf.console.domain.DataReportInfo;
import com.belf.console.domain.DataReportObject;
import com.belf.console.service.IDataReportInfoService;
import com.belf.console.service.IDataReportObjectService;
import com.belf.console.domain.AppraiseTasks;
import com.belf.console.domain.DataCheckTask;
import com.belf.console.domain.DataTaskConf;
import com.belf.console.domain.DataTaskLog;
import com.belf.console.mapper.DataTaskLogMapper;
import com.belf.console.service.IAppraiseTasksService;
import com.belf.console.service.IDataCheckTaskService;
import com.belf.console.service.IDataTaskConfService;
import com.belf.console.service.IDataTaskLogService;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

import static com.belf.common.constant.BelfCodeConstants.BELF_TASK_JOB_STATUS_RUNING;
import static com.belf.common.constant.BelfCodeConstants.BELF_TASK_JOB_STATUS_SUCCESS;
import static com.belf.common.core.domain.AjaxResult.CODE_TAG;
import static com.belf.common.core.domain.AjaxResult.DATA_TAG;

/**
 * 任务日志Service业务层处理
 * 
 * @author belf
 * @date 2024-07-25
 */
@Service
public class DataTaskLogServiceImpl implements IDataTaskLogService 
{
    private static final Logger LOGGER = LoggerFactory.getLogger(DataTaskLogServiceImpl.class.getName());
    @Autowired
    private DataTaskLogMapper dataTaskLogMapper;
    @Autowired
    private IDataReportInfoService dataReportInfoService;
    @Autowired
    private IDataReportObjectService dataReportObjectService;
    @Autowired
    private IAppraiseTasksService appraiseTasksService;
    @Autowired
    private IDataTaskConfService dataTaskConfService;
    @Autowired
    private IDataCheckTaskService dataCheckTaskService;


    @Getter
    private HashMap<Long,BlockingQueue<JSONObject>> logMap = new HashMap<>();

    /**
     * 查询任务日志
     * 
     * @param id 任务日志主键
     * @return 任务日志
     */
    @Override
    public DataTaskLog selectDataTaskLogById(Long id)
    {
        DataTaskLog dataTaskLog = dataTaskLogMapper.selectDataTaskLogById(id);
        Long taskId = dataTaskLog.getTaskId();
        String taskType = dataTaskLog.getTaskType();
        if (taskId!=null && taskType!=null){
            AppraiseTasks appraiseTasks = new AppraiseTasks(taskId,taskType);
            appraiseTasks = appraiseTasksService.selectAppraiseTasksByIdAndTaskType(appraiseTasks);
            dataTaskLog.setAppraiseTasks(appraiseTasks);

            DataTaskConf dataTaskConf = new DataTaskConf(taskId,taskType);
            dataTaskConf = dataTaskConfService.selectDataTaskConfByIdAndTaskType(dataTaskConf);
            dataTaskLog.setDataTaskConf(dataTaskConf);

            DataCheckTask dataCheckTask = new DataCheckTask(taskId,taskType);
            dataCheckTask = dataCheckTaskService.selectDataCheckTaskByIdAndTaskType(dataCheckTask);
            dataTaskLog.setDataCheckTask(dataCheckTask);
        }
        return dataTaskLog;
    }

    /**
     * 查询任务日志列表
     * 
     * @param dataTaskLog 任务日志
     * @return 任务日志
     */
    @Override
    public List<DataTaskLog> selectDataTaskLogList(DataTaskLog dataTaskLog)
    {
        List<DataTaskLog> dataTaskLogs = dataTaskLogMapper.selectDataTaskLogList(dataTaskLog);
       /* dataTaskLogs.forEach(item -> {
            String taskProgress = item.getTaskProgress();
            if (taskProgress!=null){
                JSONObject jsonArray = JSONObject.parse(taskProgress);
                jsonArray.forEach((key,value) -> {

                });
            }

        });*/
        return dataTaskLogs;
    }

    @Override
    public long selectDataCount(DataTaskLog dataTaskLog) {

        return dataTaskLogMapper.selectDataCount(dataTaskLog);
    }

    /**
     * 新增任务日志
     * 
     * @param dataTaskLog 任务日志
     * @return 结果
     */
    @Override
    public long insertDataTaskLog(DataTaskLog dataTaskLog)
    {
//        dataTaskLog.setCreateBy(SecurityUtils.getLoginUser().getUsername());
        dataTaskLog.setCreateTime(DateUtils.getNowDate());
        dataTaskLog.setUpdateTime(DateUtils.getNowDate());
        dataTaskLog.setStartTime(DateUtils.getNowDate());
        dataTaskLog.setTaskLog(new JSONArray().toJSONString());

        long l = dataTaskLogMapper.insertDataTaskLog(dataTaskLog);
        logMap.put(dataTaskLog.getId(),new LinkedBlockingQueue<JSONObject>());
        return l;
    }

    /**
     * 修改任务日志
     * 
     * @param dataTaskLog 任务日志
     * @return 结果
     */
    @Override
    public int updateDataTaskLog(DataTaskLog dataTaskLog)
    {
        dataTaskLog.setUpdateTime(DateUtils.getNowDate());

        return dataTaskLogMapper.updateDataTaskLog(dataTaskLog);
    }

    @Override
    public int updateDataTaskLogByJob(AjaxResult  ajaxResult,DataTaskLog jobLog) {
        JSONObject resultData = JSONObject.from(ajaxResult.get(DATA_TAG));
        jobLog.setTaskStatus(resultData.getLong(AjaxResult.CODE_TAG));

        jobLog.setTaskResult(ajaxResult.get("data").toString());
        jobLog.setTimeConsuming(resultData.getString("timeConsuming"));
/*        jobLog.setStartTime(resultData.getString("startTime"));
        jobLog.setEndTime(resultData.getString("endTime"));*/
        jobLog.setUpdateTime(DateUtils.getNowDate());
        return  dataTaskLogMapper.updateDataTaskLog(jobLog);
    }

    /**
     * 批量删除任务日志
     * 
     * @param ids 需要删除的任务日志主键
     * @return 结果
     */
    @Override
    public int deleteDataTaskLogByIds(Long[] ids)
    {
        return dataTaskLogMapper.deleteDataTaskLogByIds(ids);
    }

    /**
     * 删除任务日志信息
     * 
     * @param id 任务日志主键
     * @return 结果
     */
    @Override
    public int deleteDataTaskLogById(Long id)
    {
        return dataTaskLogMapper.deleteDataTaskLogById(id);
    }

    @Override
    public int deleteDataTaskLog(DataTaskLog dataTaskLog) {
        if (dataTaskLog.getIdArray()!=null){
            return  deleteDataTaskLogByIds(dataTaskLog.getIdArray());
        }else {
            return dataTaskLogMapper.deleteDataTaskLog(dataTaskLog);
        }
    }

/*    @Override
    public int clean(DataTaskLog dataTaskLog) {
        if (dataTaskLog.getIdArray()!=null){
            return  deleteDataTaskLogByIds(dataTaskLog.getIdArray());
        }else {
            return dataTaskLogMapper.deleteDataTaskLog(dataTaskLog);
        }
    }*/

    @Override
    public AjaxResult pushDataTaskLog(JSONObject body) {
        Long jobId = body.getLong("jobId");
        DataTaskLog dataTaskLog = selectDataTaskLogById(jobId);
        if (dataTaskLog != null) {

            JSONObject data = body.getJSONObject("data");
            String dataTypeStr = body.getString("dataType");
            // 判断日志事件类型
            if (dataTypeStr.equals("LOG")){
                String taskProgress = body.getString("taskProgress");
                dataTaskLog.setTaskProgress(taskProgress);


                BlockingQueue<JSONObject> logBlockingQueue = logMap.get(jobId);
                if (logBlockingQueue == null) {
                    logBlockingQueue = new LinkedBlockingQueue<>();
                    logMap.put(jobId, logBlockingQueue);
                }
                if (dataTaskLog.getJobType().equals("SYNC_DATA")&& logBlockingQueue.size()>=20){
                    //  临时存入队列，前端获取再提供
                    logBlockingQueue.poll();
                }
                    LOGGER.info("TASK {}: TYPE:{} QueueSize:{} data:{}", dataTaskLog.getId(), dataTaskLog.getJobType(), logBlockingQueue.size(),data);
                logBlockingQueue.add(data);

                updateDataTaskLog(dataTaskLog);
                return AjaxResult.success();
            }
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult pushDataTaskLogResult(JSONObject body) {
        Long jobId = body.getLong("jobId");
        DataTaskLog dataTaskLog = selectDataTaskLogById(jobId);
        if (dataTaskLog != null) {

            JSONObject resultData = JSONObject.from(body);
            Long taskStatus = resultData.getLong(CODE_TAG);

            dataTaskLog.setTaskResult(resultData.toString());
            dataTaskLog.setTaskStatus(taskStatus);
            updateDataTaskLog(dataTaskLog);
        }
        return AjaxResult.success();
    }

    @Override
    public DataTaskLog selectDataTaskLogNew(DataTaskLog dataTaskLog) {
        return dataTaskLogMapper.selectDataTaskLogNew(dataTaskLog);
    }



    @Override
    public AjaxResult selectDataTaskLogNewInfo(DataTaskLog dataTaskLog) {
        dataTaskLog = dataTaskLogMapper.selectDataTaskLogNew(dataTaskLog);
        if (dataTaskLog != null) {
            if (dataTaskLog.getTaskStatus().equals(BELF_TASK_JOB_STATUS_RUNING) || dataTaskLog.getJobType().equals("SYNC_DATA")) {
                // 获取队列日志
                BlockingQueue<JSONObject> logBlockingQueue = logMap.get(dataTaskLog.getId());
                if (logBlockingQueue == null){
                    logBlockingQueue= new LinkedBlockingQueue<JSONObject>();
                    logMap.put(dataTaskLog.getId(),logBlockingQueue);
                }
                JSONArray taskLogs=new JSONArray();
                while (!logBlockingQueue.isEmpty()){
                    taskLogs.add(logBlockingQueue.poll());
                }
                // 更新日志
                String taskLogStr = dataTaskLog.getTaskLog();
                JSONArray taskLog = JSONArray.parse(taskLogStr);
                taskLog.addAll(taskLogs);

                dataTaskLog.setTaskLog(taskLog.toJSONString());
                if (dataTaskLog.getJobType().equals("SYNC_DATA")){
                    // 更新数据库
                    // 数据同步保持任务执行中 获取日志
                    dataTaskLog.setTaskStatus(BELF_TASK_JOB_STATUS_RUNING);
                }
                updateDataTaskLog(dataTaskLog);
                // 返回日志
                dataTaskLog.setTaskLog(taskLogs.toJSONString());
                LOGGER.info(" task runing -------taskLog size {}-------taskLogs size {}--------------------------------",taskLog.size(),taskLogs.size());
                return AjaxResult.success(dataTaskLog);
            }
            return AjaxResult.success(dataTaskLog);
        }
        return AjaxResult.error();
    }

    @Override
    public void saveDataTaskLogResult(DataTaskLog jobLog) {
        if (!jobLog.getTaskStatus().equals(BELF_TASK_JOB_STATUS_RUNING)){
            LOGGER.info("task end  update taskLog ");
            DataTaskLog dataTaskLog = selectDataTaskLogById(jobLog.getId());
            String taskLogStr = dataTaskLog.getTaskLog();
//            String taskLogStr = jobLog.getTaskLog();
            JSONArray taskLogs = JSONArray.parse(taskLogStr);
            BlockingQueue<JSONObject> logBlockingQueue = logMap.get(jobLog.getId());
            LOGGER.info(" TASK end -------taskLog size {}-------taskLogs size {}--------------------------------",logBlockingQueue.size(),taskLogs.size());
            while (!logBlockingQueue.isEmpty()){
                taskLogs.add(logBlockingQueue.poll());
            }
            LOGGER.info("task end  update taskLog:{} ",taskLogs.size());
            if (taskLogs.size()>0){
                jobLog.setTaskLog(taskLogs.toJSONString());
            }
        }
        updateDataTaskLog(jobLog);
        if (!jobLog.getJobType().equals("SYNC_DATA")){
            LOGGER.info(" remove queue size :{} -",logMap.get(jobLog.getId()).size());
            logMap.remove(jobLog.getId());
        }
    }

    /**
     *  获取迁移结果报告
     * @param dataTaskLog
     * @return
     */
    @Override
    public AjaxResult selectDataTaskLogResult(DataTaskLog dataTaskLog) {
        dataTaskLog = dataTaskLogMapper.selectDataTaskLogNew(dataTaskLog);
        if (dataTaskLog != null) {
            Long taskId = dataTaskLog.getTaskId();
            Long jobId = dataTaskLog.getId();

            DataReportInfo dataReportInfo = new DataReportInfo(jobId,taskId);
            List<DataReportInfo> infoList = dataReportInfoService.selectDataReportInfoList(dataReportInfo);
            AtomicInteger tatol= new AtomicInteger();
            AtomicInteger successRate= new AtomicInteger();
            infoList.forEach(info -> {
                DataReportObject dataReportObject = new DataReportObject(jobId, taskId, info.getId());
                List<DataReportObject> dataReportObjects = dataReportObjectService.selectDataReportObjectList(dataReportObject);
                if (dataReportObjects.size() > 0) {
                    dataReportObjects.forEach(object -> {
                        if (object.getCode().equals(BELF_TASK_JOB_STATUS_SUCCESS)) {
                            info.getSuccessItems().add(object);
                        } else {
                            info.getFailureItems().add(object);
                        }
                    });
                }
                tatol.addAndGet(info.getTotal());
                successRate.addAndGet(info.getSuccessItems().size());
                info.setCompletes(info.getSuccessItems().size());
                info.setFailtures(info.getFailureItems().size());
                info.setErrorTipsCount(info.getFailureItems().size());
                if (info.getTotal()!=0){
                    info.setSuccessRate(String.format("%.2f%%", info.getCompletes() * 100.0 / info.getTotal()));
                }else {
                    info.setSuccessRate("100%");
                }
            });


            String taskResult = dataTaskLog.getTaskResult();
            if (taskResult != null) {
                JSONObject taskResultJson = JSONObject.parseObject(taskResult);
                taskResultJson.put(DATA_TAG, infoList);
                taskResultJson.put("successRate",String.format("%.2f", successRate.get() * 100.0 / tatol.get()) );
                dataTaskLog.setTaskResult(taskResultJson.toJSONString());
            }
            return AjaxResult.success(dataTaskLog);
        }
        return AjaxResult.error();
    }

    @Override
    public List<DataTaskLog> getAppraiseTaskReportList(AppraiseTasks appraiseTasks) {
        return  dataTaskLogMapper.getAppraiseTaskReportList(appraiseTasks);
    }



    public static void main(String[] args) {
        String format = String.format("%.2f%%", 1 * 100.0 / 5);
        System.out.println(format);
    }
}
